import * as XLSX from 'xlsx'
import fileSaver from 'file-saver'
import { Message } from '@zto/zui'
/**
 * 导出报价单
 * @param {*} tableColumns 表格固定列配置
 * @param {*} dynamicColumns 动态列配置
 * @param {*} tableData 规则表格数据
 * @param {*} objectColumns 对象信息表头配置
 * @param {*} objectData 对象信息数据
 * @param {*} baseInfo 基础信息数据
 * @param {*} quoteName 报价单名称
 * @param {*} exportType 导出类型exportType: all-导出报价单,object-导出对象 rules-导出规则
 */
export function handleExportQuote({ tableColumns, dynamicColumns, tableData, objectColumns, objectData, baseInfo, quoteName, exportType }) {
  // console.log('导出报价单', tableColumns, dynamicColumns, tableData, objectData, baseInfo)

  // 设置交替行背景颜色
  const alternateRowStyle = {
    fill: { fgColor: { rgb: 'F2F2F2' } }
  }

  try {
    // 1. 构建基础信息数据
    const baseHeaders = ['基础信息']
    const baseData = baseInfo
      .map(item => {
        const rowData = [item.label, item.value]
        return rowData
      })
      .reduce((accumulator, currentValue) => {
        return accumulator.concat(currentValue)
      }, [])

    // 2. 构建报价单表头和数据

    const filterColumns = dynamicColumns.filter(item => !['destinationAreaGroup'].includes(item.prop))

    const headers = ['目的地区域组', '地区', ...filterColumns.map(col => col.label)]

    const data = tableData.map((row, index) => {
      const rowData = [row.destinationAreaGroup, row.areaList.join('、')]

      filterColumns.forEach(col => {
        const formulaValue = row[col.prop]
        // console.log(col.prop, formulaValue)
        rowData.push(formulaValue)
      })

      return rowData
    })

    // 3. 构建对象信息表头和数据
    const objHeaders = objectColumns.map(item => item.label)
    const objData = objectData.map(item => {
      // 根据objHeaders有哪些字段，从item中取出对应的值
      return objectColumns.map(col => item[col.prop])
    })

    // 4. 创建工作簿和合并数据
    const wb = XLSX.utils.book_new()

    // 合并所有数据到一个数组，基础信息放在最上面
    const allData = [
      [quoteName],
      ['基础信息'], // 基础信息标题行
      baseData,
      [], // 空行分隔
      [] // 空行分隔
    ]

    if (exportType === exportTypeEmum.object) {
      allData.push(...[objHeaders, ...objData])
    } else if (exportType === exportTypeEmum.rules) {
      allData.push(...[headers, ...data])
    } else {
      allData.push(...[objHeaders, ...objData, [], [], headers, ...data])
    }

    // 5. 创建工作表
    const ws = XLSX.utils.aoa_to_sheet(allData)

    // 6. 设置列宽
    const colWidths = [
      { wch: 15 }, // 基础信息字段
      { wch: 20 }, // 基础信息值
      { wch: 30 }, // 对象名称
      { wch: 20 }, // 生效时间
      { wch: 15 }, // 目的地区域组
      { wch: 30 }, // 地区
      ...dynamicColumns.map(() => ({ wch: 25 })) // 重量段
    ]
    ws['!cols'] = colWidths

    // 7. 设置合并单元格
    const objTitleStartRow = baseData.length + 4 // 对象信息标题开始行

    // ws['!merges'] = [
    //   // 基础信息标题合并
    //   {
    //     s: { r: 0, c: 0 },
    //     e: { r: 0, c: baseTitleEndCol }
    //   },
    //   // 对象信息标题合并
    //   {
    //     s: { r: objTitleStartRow, c: 0 },
    //     e: { r: objTitleStartRow, c: objTitleEndCol }
    //   },
    //   // 报价单标题合并
    //   {
    //     s: { r: quoteTitleStartRow, c: 0 },
    //     e: { r: quoteTitleStartRow, c: quoteTitleEndCol }
    //   }
    // ]

    // 8. 应用样式
    // const range = XLSX.utils.decode_range(ws['!ref']) // 获取数据的范围
    // console.log(range, 'range')
    // for (let R = range.s.r; R <= range.e.r; ++R) {
    //   for (let C = range.s.c; C <= range.e.c; ++C) {
    //     const cellAddress = { c: C, r: R } // 单元格地址
    //     const cellRef = XLSX.utils.encode_cell(cellAddress) // 单元格引用

    //     // 设置单元格样式，例如：设置背景色和字体颜色
    //     if (!ws[cellRef]) continue // 如果单元格不存在，则跳过
    //     const cell = ws[cellRef]
    //     if (!cell.s) cell.s = {} // 如果样式不存在，则创建它
    //     cell.s.bgFill = { rgb: 'FFFF00' } // 背景色为黄色
    //     cell.s.font = { color: { rgb: 'FF0000' }, bold: true } // 字体颜色为红色，加粗
    //   }
    // }
    // 9. 添加工作表到工作簿
    XLSX.utils.book_append_sheet(wb, ws, '报价单')

    // 10. 生成并保存文件
    const wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'array' })
    const blob = new Blob([wbout], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })

    // 11. 保存文件
    const fileName = `报价单_${new Date().toLocaleDateString()}.xlsx`
    fileSaver.saveAs(blob, fileName)

    Message.success('导出成功')
  } catch (error) {
    console.error('导出失败:', error)
    Message.error('导出失败，请重试')
  }
}

/**
 * 扁平化数组-递归
 */
export function getDefaultProvince() {
  // 扁平化处理函数
  function flattenData(data) {
    const result = []
    data.forEach(item => {
      if (item.children && item.children.length > 0) {
        result.push(...item.children)
      }
    })
    return result
  }
  return flattenData(regionProvinceList.filter(item => item.label !== '特殊管区'))
}

/**
 * 动态列和行生成双向绑定数据
 * @param {} rules
 * @returns
 */
export function handleTransferData(rules) {
  const outputArray = []
  const columns = rules
    .filter(item => item.groupIndex === 0)
    .map((item, colIndex) => ({
      startWeight: item.startWeight,
      endWeight: item.endWeight,
      weightKey: colIndex,
      minWidth: '460px'
    }))

  const groups = rules.reduce(
    (acc, curr) => {
      const { groupIndex } = curr
      if (!acc.seenGroupIndexes[groupIndex]) {
        acc.result.push(curr)
        acc.seenGroupIndexes[groupIndex] = true
      }
      return acc
    },
    { result: [], seenGroupIndexes: {} }
  )

  function findRule(descCodes, startWeight, endWeight) {
    return rules.find(item => item.descCodes === descCodes && item.startWeight === startWeight && item.endWeight === endWeight)
  }
  groups.result.forEach(row => {
    const areaList = row.descNames.split(',').map((name, index) => ({
      label: name,
      id: row.descCodes.split(',')[index]
    }))
    const transformedItem = { areaList, destinationAreaGroup: row.groupName }

    columns.forEach((column, weightKey) => {
      const formula0Key = `formula0${weightKey}` // 元/票
      const formula1Key = `formula1${weightKey}` // 元/票
      const formula2Key = `formula2${weightKey}` // 元/kg
      const formula3Key = `formula3${weightKey}` // 基础重量
      const formula4Key = `formula4${weightKey}` // 阶梯价格
      const formulaTypeKey = `formulaType${weightKey}` // 阶梯价格
      transformedItem[formula0Key] = undefined
      transformedItem[formula1Key] = undefined
      transformedItem[formula2Key] = undefined
      transformedItem[formula3Key] = undefined
      transformedItem[formula4Key] = undefined
      transformedItem[formulaTypeKey] = undefined
      const rule = findRule(row.descCodes, column.startWeight, column.endWeight)
      const { item, baseWeight, itemValue, item2Value, itemUnit, item2Unit } = rule.extendJsonFormat[0]

      console.log(transformedItem, 'transformedItem')
    })
    outputArray.push(transformedItem)
  })
  // console.log(outputArray, this.$refs.quoteRuleRef, 'quoteRuleRef')
  // context.$nextTick(() => {
  //   context.$refs.quoteRuleRef && context.$refs.quoteRuleRef.setTableData(outputArray, columns)
  // })
  return {
    outputArray,
    columns
  }
}

/**
 * 查找两个数组的交集
 * @param {*} arr1 数组1
 * @param {*} arr2 数组2
 * @param {*} key 查找的key
 * @returns 重合元素
 */
export const findSameElements = (arr1, arr2, key) => {
  return arr1.filter(item => arr2.some(n => n[key] === item[key]))
}

/**
 * 查找两个数组的差集
 * @param {*} arr1 数组1
 * @param {*} arr2 数组2
 * @param {*} key 查找的key
 * @returns 差集
 */
export const findDifference = (arr1, arr2, key) => {
  return arr1.filter(item => !arr2.some(n => n[key] === item[key]))
}

/**
 * 快捷选择-地区选中省份列表更新
 * @param {*} value
 */
function handleProvinceSelect(value) {
  const selectedProvinces = []

  value.forEach(selectedRegion => {
    const regionData = this.quickSelectList.find(item => item.label === selectedRegion)

    if (regionData && regionData.children) {
      selectedProvinces.push(...regionData.children)
    }
  })
  // 更新选中的省份列表
  this.defaultPROVINCESelectList = selectedProvinces
  this.$refs.destinationContentRef.initData()
}

// 省份数据更新-快捷选择联动更新
function handleQuickSelect(dataList) {
  this.formData.destinationQuickSelect = []
  const checkProvincesIncluded = (baseArray, checkArray) => {
    const baseIds = new Set(baseArray.map(province => province.id))
    return checkArray.every(province => baseIds.has(province.id))
  }
  console.log(dataList, 'areaList')
  // 遍历所有的快捷选择quickSelectList，如果areaList中包含某个快捷选择，则将快捷选择的formData.destinationQuickSelect更新
  regionProvinceList.forEach(area => {
    // 判断当前组下的是否全包含在areaList中
    const flag = checkProvincesIncluded(
      dataList.map(item => ({ ...item, id: Number(item.id) })),
      area.children
    )
    if (flag) {
      this.formData.destinationQuickSelect.push(area.label)
    }
  })
}

/**
 * 按照对象编码查找当前分组的开始索引和结束索引返回内容[0,2]
 * @param {*} tableData 
 * @param {*} groupKeys 
 * @returns 
 */
export function getGroupIndexes(tableData, groupKeys) {
  // groupKey 为数组时，需要根据数组中的每个值进行分组
  if (!Array.isArray(groupKeys)) return []
  const indexes = {}
  // 根据groupKeys的值进行分组，计算出该组的首行和末行index
  tableData.forEach((row, index) => {
    const values = groupKeys.map(key => row[key])
    const unique = values.join('').toString()
    if (!indexes[unique]) {
      indexes[unique] = [index, index]
    } else {
      indexes[unique][1] = index
    }
  })
  return indexes
}

/**
 * 开始和结束重量段处理，段连续，有最大值，有分组，没有分组的情况下直接去除分组逻辑即可
 * 2025年4月18日：下一行唯一盘判断根据分组key判断
 * @param {Array} tableData 表格数据
 * @param {Object} row 当前行数据
 * @param {Number} index 当前行索引
 * @param {Number} maxValue 最大值
 * @param {Boolean} isDel 是否删除
 * @param {String} startKey 开始重量段key
 * @param {String} endKey 结束重量段key
 */
async function handleTableData({ tableData, row, index, maxValue, isDel, startKey, endKey, hasGroup, groupKeys, errorMessage }) {
  const allData = cloneDeep(tableData)
  const startWeight = row[startKey]
  const endWeight = row[endKey]
  const nextRow = allData[index + 1]
  const preRow = allData[index - 1]
  const groupIndexes = getGroupIndexes(tableData, groupKeys)
  const values = groupKeys.map(key => row[key])
  const uniqueValue = values.join('')
  // 当前组的最后一条
  const isLastRow = hasGroup ? index === groupIndexes[uniqueValue][1] : index === allData.length - 1
  // 当前组的第一条
  const isFirstRow = hasGroup ? index === groupIndexes[uniqueValue][0] : index === 0
  // 当前行和下一行的key
  const currentRowKey = groupKeys.map(key => row[key]).join('')
  const nextRowKey = nextRow ? groupKeys.map(key => nextRow[key]).join('') : ''

  // 更新当前行数据
  const updateRow = (sWeight, eWeight, updateIndex) => {
    allData[updateIndex][startKey] = sWeight
    allData[updateIndex][endKey] = eWeight
  }
  // 删除数据
  const handleDelete = (sWeight, eWeight, updateIndex) => {
    updateRow(sWeight, eWeight, updateIndex)
    allData.splice(index, 1)
  }

  const handleAddRow = () => {
    const newRow = {
      ...row,
      [startKey]: endWeight,
      [endKey]: maxValue
    }
    // 在index后插入一条
    allData.splice(index + 1, 0, newRow)
  }

  if (isDel) {
    await MessageBox.confirm(errorMessage || '是否确定删除?')
    // 删除逻辑
    // 删除最后一段，直接删除，更新前一段的结束值为最大值即可
    if (isLastRow) {
      handleDelete(preRow[startKey], maxValue, index - 1)
      return Promise.resolve(allData)
    }
    if (isFirstRow) {
      // 更新下一行的值开始值
      handleDelete(0, nextRow[endKey], index + 1)
      return Promise.resolve(allData)
    }
    // 不是最后一行
    // 更新上一行的结束值
    allData.splice(index, 1)
    updateRow(preRow[startKey], nextRow[startKey], index - 1)
    return Promise.resolve(allData)
  }

  // 判断是否在同一个分组，在同一个分组
  if ((startWeight === undefined || endWeight === undefined) && currentRowKey === nextRowKey) {
    updateRow(startWeight, nextRow ? nextRow[startKey] : maxValue, index)
    return Promise.resolve(allData)
  }
  if ((startWeight === undefined || endWeight === undefined) && currentRowKey !== nextRowKey) {
    updateRow(startWeight, maxValue, index)
    return Promise.resolve(allData)
  }

  // 判断是否在同一个组
  if (hasGroup && nextRow && currentRowKey !== nextRowKey) {
    if (endWeight <= startWeight) {
      const endWeight1 = isLastRow ? maxValue : nextRow[startKey]
      updateRow(startWeight, endWeight1, index)
      return Promise.resolve(allData)
    }
    // 插入一条数据
    handleAddRow()
    return Promise.resolve(allData)
  }
  // 不存在最后一条直接添加

  // 校验逻辑
  // 不能大于当前行的开始重量段
  if (endWeight <= startWeight) {
    const endWeight1 = isLastRow ? maxValue : nextRow[startKey]
    updateRow(startWeight, endWeight1, index)
    return Promise.resolve(allData)
  }
  // 校验不能大于下一行的结束重量段
  if (nextRow) {
    if (endWeight >= nextRow[endKey]) {
      updateRow(startWeight, nextRow[startKey], index)
      return Promise.resolve(allData)
    }
    if (endWeight < nextRow[endKey]) {
      updateRow(endWeight, nextRow[endKey], index + 1)
      return Promise.resolve(allData)
    }
  }
  // 判断是否有下一行数据-更新下一行数据
  handleAddRow()

  // allData.push(newRow)
  return Promise.resolve(allData)
}
// 重量段校验
function handleEndWeightChange(isDel, row, index) {
  // 更新合并单元格
  this.$nextTick(async () => {
    this.tableData = await this.handleTableData(this.tableData, row, index, 100, isDel, 'startRate', 'endRate')
    this.getCombineInfo(this.tableData)
  })
}
